package cn.lyf.myblog.service;

import com.fasterxml.jackson.databind.node.*;

import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.Service;

import static cn.lyf.myblog.controller.api.JsonUtils.*;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.lyf.myblog.mybatis.entity.*;
import cn.lyf.myblog.mybatis.mappers.*;

@Service
public class BlogService {

    @Autowired
    BlogMapper blogMapper;

    @Autowired
    UserInfo2Mapper userInfo2Mapper;

    @Autowired
    FavoritesBlogMapper favoritesBlogMapper;

    public Blog getBlogByBid(int bid) {
        return blogMapper.selectById(bid);
    }

    public ObjectNode getBlogInfo(int bid) throws Exception {
        Blog blog = blogMapper.selectById(bid);
        ObjectNode res = mapper.createObjectNode();
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "博客获取成功！");
        res.set("result", mapper.valueToTree(getMoreUserInfo(blog)));
        return res;
    }

    Map<String, Object> getMoreUserInfo(Blog blog) {
        @SuppressWarnings("unchecked")
        Map<String, Object> map = mapper.convertValue(blog, Map.class);
        map.remove("uid");
        map.put("author", userInfo2Mapper.selectUserInfo2ById(blog.getUid()));
        return map;
    }

    public ObjectNode getBlogLately(ObjectNode json) throws Exception {
        Integer uid = getInteger(json, "/uid");
        Integer pageNo = getInteger(json, "/pageNo");
        Integer limit = getInteger(json, "/pageSize");
        ObjectNode res = mapper.createObjectNode();
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "博客列表获取成功！");
        List<Blog> blogs = blogMapper.selectBlogLately(uid, limit, pageNo * limit);
        res.putPOJO("result", blogs.stream().map(this::getMoreUserInfo).collect(Collectors.toList()));
        return res;
    }

    public Map<String, Object> getDetailedBlogMap(int bid) {
        return getMoreUserInfo(blogMapper.selectById(bid));
    }

    public ObjectNode upLoadBlog(ObjectNode json) throws Exception {
        String staticPath = getString(json, "/staticPath");
        String name = getString(json, "/name");
        String dir = getString(json, "/dir");
        new Thread() {
            public void run() {
                File f = new File(staticPath + dir, name);
                try (FileOutputStream fos = new FileOutputStream(f);) {
                    fos.write(getString(json, "/content", "").getBytes());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
        }.start();
        Blog blog = mapper.readValue(json.toString(), Blog.class);
        blog.setFavorites(1);
        blog.setUrl(name);
        ObjectNode res = mapper.createObjectNode();
        blogMapper.insertBlog(blog);
        favoritesBlogMapper.insertFavoritesBlog(getInteger(json, "/fid"), blog.getBid());
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "博客发布成功！");
        return res;
    }

    public ObjectNode deleteBlog(ObjectNode json) throws Exception {
        Blog blog = blogMapper.selectById(getInteger(json, "/bid"));
        ObjectNode res = mapper.createObjectNode();
        if (blog == null) {
            res.put("success", false);
            res.put("code", 469);
            res.put("message", "博客不存在！");
            return res;
        }
        File file = new File(getString(json, "/path") + blog.getUrl());
        if (file.exists())
            file.delete();
        blogMapper.deleteBlog(blog.getBid());
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "博客删除成功！");
        return res;
    }

    public ObjectNode updateBlog(ObjectNode json) throws Exception {
        Blog blog = mapper.readValue(json.toString(), Blog.class);
        blogMapper.updateBlogNotNull(blog);
        String content = getString(json, "/content");
        String filePath = getString(json, "/path") + getString(json, "/dir") + blog.getUrl();
        if (content != null) {
            new Thread() {
                public void run() {
                    try (FileOutputStream fos = new FileOutputStream(new File(filePath));) {
                        fos.write(content.getBytes());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                };
            }.start();
        }
        ObjectNode res = mapper.createObjectNode();
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "博客修改成功！");
        return res;
    }

    public ObjectNode getArchives(int uid) throws Exception {
        ObjectNode res = mapper.createObjectNode();
        res.putPOJO("result", blogMapper.selectByYearAndUid(uid).parallelStream().map((m) -> {
            m.put("list", blogMapper.selectByYear(Integer.parseInt((String) m.get("year"))));
            return m;
        }).collect(Collectors.toList()));
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "归档成功！");
        return res;
    }

    public ObjectNode getBlogByFavorites(Integer fid) throws Exception {
        ObjectNode res = mapper.createObjectNode();
        res.put("success", true);
        res.put("code", 200);
        res.put("message", "收藏夹查询成功");
        return res.putPOJO("result", favoritesBlogMapper.selecFavoritesBlogById(fid).stream().map(bid -> {
            return blogMapper.selectById(bid);
        }).map(this::getMoreUserInfo));
    }

    public int getSum(int uid) {
        return blogMapper.selectSumByUid(uid);
    }

    public List<Blog> search(String title, List<String> tags, Integer uid) {
        title = "%" + title + "%";
        List<Blog> res = blogMapper.seletByTagsAndTitle(title, tags);
        if (uid != null) {
            return res.parallelStream().filter(blog -> blog.getUid() == uid).collect(Collectors.toList());
        }
        return res;
    }
}
